package io.persimmon.core.module.thread;

import lombok.extern.slf4j.Slf4j;

import java.util.Objects;
import java.util.concurrent.*;
import java.util.concurrent.atomic.AtomicInteger;

@Slf4j
public class ThreadPool {
    private static final AtomicInteger THREAD_NUM = new AtomicInteger(1);
    public static ThreadPoolExecutor INSTANCE;
    public static int CORE_POOL_SIZE = Runtime.getRuntime().availableProcessors();
    public static int MAXIMUM_POOL_SIZE = Runtime.getRuntime().availableProcessors() * 2;
    public static long KEEP_ALIVE_TIME = 600;
    public static int BLOCKING_QUEUE_SIZE = 10;
    public static String THREAD_NAME_PREFIX = "persimmon-thread-";
    public static RejectedExecutionHandler rejectedExecutionHandler = new ThreadPoolExecutor.CallerRunsPolicy() {
        @Override
        public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {
            super.rejectedExecution(r, e);
            log.warn("Thread pool is full, rejecting task, poolSize:{}, remainingCapacity:{}", e.getPoolSize(), e.getQueue().remainingCapacity());
        }
    };
    public static ThreadFactory threadFactory = r -> {
        Thread thread = new Thread(r);
        thread.setName(THREAD_NAME_PREFIX + thread.getId() + "-" + THREAD_NUM.getAndAdd(1));
        return thread;
    };

    public static ThreadPoolExecutor getInstance() {
        if (Objects.isNull(INSTANCE)) {
            synchronized (ThreadPool.class) {
                if (Objects.isNull(INSTANCE)) {
                    INSTANCE = new ThreadPoolExecutor(CORE_POOL_SIZE,
                            MAXIMUM_POOL_SIZE,
                            KEEP_ALIVE_TIME, TimeUnit.SECONDS,
                            new LinkedBlockingQueue<>(BLOCKING_QUEUE_SIZE),
                            threadFactory,
                            rejectedExecutionHandler
                    );
                }
            }
        }
        return INSTANCE;
    }
}
